package com.pz.cloud.framework.business.workflow.aspect;

import com.pz.cloud.framework.business.workflow.annotation.WorkflowVariable;
import com.pz.cloud.framework.business.workflow.entity.ProcessBind;
import com.pz.cloud.framework.base.model.WorkflowEntity;
import com.pz.cloud.framework.business.workflow.enums.WorkflowEnum;
import com.pz.cloud.framework.business.workflow.model.WorkflowModel;
import com.pz.cloud.framework.business.workflow.service.IProcessBindService;
import com.pz.cloud.framework.business.workflow.service.IWorkflowService;
import com.pz.cloud.framework.util.BizUtil;
import com.pz.cloud.framework.business.workflow.annotation.Workflow;
import com.pz.cloud.framework.business.workflow.model.BaseTaskCallback;
import com.pz.cloud.framework.util.FieldUtil;
import com.pz.cloud.framework.util.WorkflowUtil;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.jeecg.common.util.SpringContextUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.util.CollectionUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
 * 工作流切面类
 * @author mzz
 */
@Aspect
@Order(1)
@Component
public class WorkflowAspect {


    @Autowired
    private PlatformTransactionManager transactionManager;
    @Autowired
    private IWorkflowService workflowService;
    @Autowired
    private IProcessBindService processBindService;


    @Around("@annotation(com.pz.cloud.framework.business.workflow.annotation.Workflow)")
    public Object submit(ProceedingJoinPoint joinPoint) throws Throwable{
        Object result = null;
        Object[] args = joinPoint.getArgs();
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        TransactionStatus status = transactionManager.getTransaction(def);
        try {
            result = joinPoint.proceed();
            Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
            Workflow workflow = method.getAnnotation(Workflow.class);
            Class callback =  workflow.callback();
            BaseTaskCallback taskCallback = null;
            if(callback!=null ){
                Object callBackObj = SpringContextUtils.getBean(callback);
                if(callBackObj instanceof BaseTaskCallback){
                    taskCallback = (BaseTaskCallback) callBackObj;
                }
            }
            for (Object arg : args) {
                if(arg instanceof WorkflowEntity){
                    WorkflowModel workflowModel = ((WorkflowEntity) arg).getWorkflowModel();
                    if(StringUtils.isNotEmpty(workflowModel.getOperation())){

                        //设置流程所需变量
                        WorkflowUtil.setWorkflowVariable(((WorkflowEntity) arg));

                        String id = BizUtil.getIdFieldValue(arg);
                        if(StringUtils.isNotEmpty(id)){
                            workflowModel.setRelatedId(id);
                        }

                        workflowModel.setRelatedTable(((WorkflowEntity)arg).getTableName());
                        String callbackName = BizUtil.getBeanName(taskCallback.getClass());
                        workflowModel.setCallback(callbackName);
                        workflowService.submit(workflowModel);
                        //回调
                        if(taskCallback!=null){
                            taskCallback.execute((WorkflowEntity) arg);
                        }
                    }
                }
            }
            transactionManager.commit(status);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            transactionManager.rollback(status);
            throw throwable;
        }
        return result;
    }
//    private void setWorkflowVariable(WorkflowEntity entity) throws IllegalAccessException {
//        WorkflowModel workflowModel = entity.getWorkflowModel();
//
//        Field[] fields = FieldUtil.getAllFields(entity.getClass());
//        for (Field field : fields) {
//            if(field.isAnnotationPresent(WorkflowVariable.class)){
//                field.setAccessible(true);
//                Object value = field.get(entity);
//                if(value!=null&&!"".equals(value)){
//                    WorkflowVariable workflowVariable = field.getAnnotation(WorkflowVariable.class);
//                    WorkflowEnum name = workflowVariable.name();
//                    switch (name){
//                        case TITLE:
//                            workflowModel.setTitle(value.toString());
//                            break;
//                        case NUMBER:
//                            workflowModel.setNumber(value.toString());
//                            break;
//                    }
//                }
//            }
//        }
//
//
//        ProcessBind processBind = processBindService.findProcessBind(entity);
//        if(processBind==null){
//            List<ProcessBind> processBinds = processBindService.findByRelatedTable("default");
//            if(!CollectionUtils.isEmpty(processBinds)){
//                processBind = processBinds.get(0);
//            }
//        }
//        if(processBind!=null){
//            workflowModel.setProcessKey(processBind.getProcessKey());
//            workflowModel.setProcessBindId(processBind.getId());
//            if(StringUtils.isEmpty(workflowModel.getTitle())){
//                String titleExpression = processBind.getTitleExpression();
//                String reg = "\\$\\{[\\s\\S]*}";
//                Pattern pattern =  Pattern.compile(reg);
//                Matcher matcher = pattern.matcher(titleExpression);
//                while (matcher.find()){
//                    String group = matcher.group();
//                    String fieldName = group.substring(2, group.length() - 1);
//
//                    Object fieldValue = FieldUtil.getFieldValueByName(entity, fieldName);
//                    if(fieldValue!=null){
//                        titleExpression = titleExpression.replace(group,fieldValue.toString());
//                    }
//                }
//                workflowModel.setTitle(titleExpression);
//            }
//        }
//
//
//
//
//    }
}